package team.nmsg.ge.system.init;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import team.nmsg.ge.system.bean.PageMenu;
import team.nmsg.ge.system.bean.SysOper;
import team.nmsg.ge.system.bean.SysRole;
import team.nmsg.ge.system.bean.SysUser;
import team.nmsg.ge.system.util.ServerParams;
import team.nmsg.ge.system.util.SysDBHelper;

public class InitSystemAuth {
	
	
	private static Logger logger =  LoggerFactory.getLogger(  InitSystemAuth.class );
	
	
	public static String FILE_PATH = ServerParams.BASE_CONF_PATH + "SysUserAndAuth.xml";
	
	private final static String TAG_MENUGROUP = "MenuGroup";
	private final static String TAG_MENUS  = "Menus";
	private final static String TAG_MENU = "Menu";
	private final static String TAG_OPER = "Oper";	
	
	private final static String ATTR_NAME = "name";
	private final static String ATTR_URL = "url";
	private final static String ATTR_ICON = "icon";
	private final static String ATTR_DESC = "desc";
	private final static String ATTR_AUTHURL = "auth_url";
	
	public static SysRole admins = null;
	

	private static List<PageMenu> pageMenus = new ArrayList<PageMenu>();
	private static Map<String, PageMenu> idToMenu = new HashMap<String , PageMenu>();
	
	
	public static void loadSysAuth(){
		
		File file = new File(FILE_PATH);
		SAXReader reader = new SAXReader();
		Document doc = null;
		try {
			doc = reader.read(file);
		} catch (Exception e) {
			logger.error("Cant read file:::" + FILE_PATH , e );
			return;
		}
		Element root = doc.getRootElement();
		
		Session hSession = SysDBHelper.getHelper().openHSession();
		Transaction transaction = null;
		try {
			transaction = hSession.beginTransaction();
			Element adminRole = root.element("AdminRole");
			admins = parseAdmin(adminRole , hSession);
			
			parseAuth( root , hSession );
			
			transaction.commit();
		} catch (Exception e) {
			logger.error(" " , e );
			transaction.rollback();
		}finally{
			hSession.close();
		}
		
		//创建整理成树
		Collection<SysOper> values = nameToOper.values();
		Iterator<SysOper> iter1 = values.iterator();
		while( iter1.hasNext() ){
			SysOper next = iter1.next();
			PageMenu tmpMenu = new PageMenu(next);
			int mtype = tmpMenu.getMtype();
			if(  SysOper.OTYPE_MENUGROUP == mtype  ){
				pageMenus.add(tmpMenu);
			}
			idToMenu.put(tmpMenu.getId(), tmpMenu);
		}
		Iterator<SysOper> iter2 = values.iterator();
		while(iter2.hasNext() ){
			SysOper next = iter2.next();
			Integer otype = next.getOtype();
			if(  otype.intValue() == SysOper.OTYPE_OPER ){
				continue;
			}
			String poId = next.getPoId().toString();
			if( ! "-1".equals(poId) ){
				PageMenu parent = idToMenu.get(poId);
				String cId = next.getOperId().toString();
				PageMenu child = idToMenu.get(cId);
				parent.addChild(child);
			}
		}
		
		SysServletContextListener.j2eeApplication.setAttribute("_allMenu", pageMenus );
	}
	
	
	private static Map<String, SysOper> nameToOper = new LinkedHashMap<String, SysOper>();
	private static void parseAuth(Element root, Session hSession) {
		
		Criteria cirteria = hSession.createCriteria(SysOper.class);
		List list = cirteria.list();
		if( list != null ){
			int size = list.size();
			for( int i=0; i<size ;i++ ){
				SysOper oper = (SysOper) list.get(i);
				String operName = oper.getOperName();
				nameToOper.put(operName, oper);
			}
		}
		
		List<Element> menuGroups = root.elements(TAG_MENUGROUP);
		Iterator<Element> iter = menuGroups.iterator();
		while(  iter.hasNext() ){
			Element oneMenuGroup = iter.next();
			List<Element> childs = oneMenuGroup.elements();
			
			String name = oneMenuGroup.attributeValue(ATTR_NAME);
			String url = null;
			String icon=  oneMenuGroup.attributeValue(ATTR_ICON);
			String desc= null;
			SysOper cOper = saveOrGetOper(name , SysOper.OTYPE_MENUGROUP , -1 , url , icon , desc , null, hSession);
			
			int childSize1 = childs.size();
			for( int i=0; i<childSize1 ;i++ ){
				Element oneMenus = childs.get(i);
				String tagName = oneMenus.getName();
				if(  TAG_MENUS.equals(tagName) ){
					String aName = oneMenus.attributeValue(ATTR_NAME);
					String aUrl = oneMenus.attributeValue(ATTR_URL);
					String aIcon = oneMenus.attributeValue(ATTR_ICON);
					String aDesc = oneMenus.attributeValue(ATTR_DESC);
					SysOper tmpMenusOper = saveOrGetOper(aName, SysOper.OTYPE_MENUS, 
							cOper.getOperId(), aUrl, aIcon, aDesc, null, hSession);
					
					List<Element> mes = oneMenus.elements();
					int size = mes.size();
					for( int  ind = 0 ; ind<size ; ind++ ){
						Element element = mes.get(ind);
						parseMenu(element , tmpMenusOper , hSession);
					}
					
				}else if( TAG_MENU.equals(tagName)  ){
					parseMenu(oneMenus , cOper , hSession);
				}
			}
		}
	}
	

	private static void parseMenu(Element oneMenu, SysOper parentOper, Session hSession) {
		String aName = oneMenu.attributeValue(ATTR_NAME);
		String aUrl = oneMenu.attributeValue(ATTR_URL);
		String aIcon = oneMenu.attributeValue(ATTR_ICON);
		String aDesc = oneMenu.attributeValue(ATTR_DESC);
		SysOper tmpMenuOper = saveOrGetOper(aName, SysOper.OTYPE_MENU,  
				parentOper.getOperId(), aUrl, aIcon, aDesc, null, hSession);
		
		List<Element> childOpers = oneMenu.elements();
		int size = childOpers.size();
		for( int i=0; i<size ;i++ ){
			Element oneOper = childOpers.get(i);
			aName = oneOper.attributeValue(ATTR_NAME);
			aUrl = oneOper.attributeValue(ATTR_URL);
			aIcon = oneOper.attributeValue(ATTR_ICON);
			aDesc = oneOper.attributeValue(ATTR_DESC);
			String authUrl = oneOper.attributeValue(ATTR_AUTHURL);
			SysOper tmpOper= saveOrGetOper(aName, SysOper.OTYPE_OPER,  
					tmpMenuOper.getOperId(), aUrl, aIcon, aDesc, authUrl, hSession);
			
		}
	}


	private static SysOper saveOrGetOper(String name,  int type , int parentId 
			, String url, String icon, String desc ,String authUrl, Session hSession) {
		
		SysOper retOper = nameToOper.get(name);
		if( retOper == null ){
			retOper = new SysOper();
			retOper.setOperName(name);
			retOper.setOtype(type);
			retOper.setIcon(icon);
			retOper.setUrl(url);
			retOper.setOperRemark(desc);
			retOper.setPoId(parentId);
			retOper.setAuthUrl(authUrl);
			Serializable save = hSession.save(retOper);
			hSession.flush();
			retOper = hSession.get(SysOper.class, save);
			nameToOper.put(name, retOper);
			
			Set<SysOper> opers = admins.getOpers();
			if( opers == null ){
				opers = new HashSet<SysOper>();
				admins.setOpers(opers);
			}
			opers.add(retOper);
			hSession.saveOrUpdate(retOper);
			hSession.flush();
		}
		
		return retOper;
	}

	private static SysRole parseAdmin(Element adminRole, Session hSession) {
		SysRole roleResult = null;
		SysUser userResult = null;
		try {
			Element admin = adminRole.element("User");
			String uname = admin.attributeValue("username");
			String upass = admin.attributeValue("password");
			String userRemark = admin.attributeValue("userRemark");
			
			userResult = isExistUserName(uname , hSession);
			if( userResult==null ){
				SysUser sysUser = new SysUser();
				sysUser.setUsername(uname);
				sysUser.setPassword(upass);
				sysUser.setUserRemark(userRemark);
				long nowTime = System.currentTimeMillis();
				sysUser.setCreateTimestamp(nowTime);
				sysUser.setLastUpdateTimestamp(nowTime);
				sysUser.setUserStatus(SysUser.USER_STATUS_NORMAL);
				userResult = addSysUser(sysUser , hSession);
			}
			
			Element role = adminRole.element("Role");
			String roleName = role.attributeValue("roleName");
			String roleRemark = role.attributeValue("roleRemark");
			roleResult = findSysRoleByName(roleName , hSession );
			if( roleResult==null  ){
				 SysRole sysRole = new SysRole();
				 sysRole.setRoleName(roleName);
				 sysRole.setRoleRemark(roleRemark);
				 sysRole.setCreateTimestamp(System.currentTimeMillis());
				 roleResult = addSysRole(sysRole , hSession);
			}
			Set<SysRole> roles = userResult.getRoles();
			if( roles == null ){
				roles = new HashSet<SysRole>();
				roles.add(roleResult);
				userResult.setRoles(roles);
				hSession.saveOrUpdate(userResult);
				hSession.flush();
			}
			
		} catch (Exception e) {
			logger.error("Admin Role Parse Error:::" , e);
		}
		return roleResult;
	}

	private static SysRole addSysRole(SysRole nmsRole, Session hSession) {
		
		Serializable save = hSession.save(nmsRole);
		SysRole sysRole = hSession.get(SysRole.class, save);
		
		return sysRole;
	}


	private static SysRole findSysRoleByName(String roleName, Session hSession) {
		Criteria cirteria = hSession.createCriteria(SysRole.class);
		cirteria.add(Restrictions.eq("roleName", roleName) );
		List list = cirteria.list();
		if( list!=null && list.size()>0 ){
			Object object = list.get(0);
			return (SysRole) object;
		}
		return null;
	}

	private static SysUser addSysUser(SysUser toSaveUser, Session hSession) {
		Serializable save = hSession.save(toSaveUser);
		SysUser retUser = hSession.get(SysUser.class, save);
		return retUser;
	}

	private static SysUser isExistUserName(String uname, Session hSession) {
		Criteria cirteria = hSession.createCriteria(SysUser.class);
		cirteria.add(Restrictions.eq("username", uname) );
		List list = cirteria.list();
		if( list!=null && list.size()>0 ){
			Object object = list.get(0);
			return (SysUser) object;
		}
		return null;
	}
	
	
}
